2 using System
.Collections
;
3 using System
.Collections
.Generic
;
5 using UnityEngine
.Tilemaps
;
10 [CustomGridBrush(true, false, false, "Line Brush")]
11 public class LineBrush
: GridBrush
13 public bool lineStartActive
= false;
14 public bool fillGaps
= false;
15 public Vector3Int lineStart
= Vector3Int
.zero
;
17 public override void Paint(GridLayout grid
, GameObject brushTarget
, Vector3Int position
)
21 Vector2Int startPos
= new Vector2Int(lineStart
.x
, lineStart
.y
);
22 Vector2Int endPos
= new Vector2Int(position
.x
, position
.y
);
23 if (startPos
== endPos
)
24 base.Paint(grid
, brushTarget
, position
);
27 foreach (var point
in GetPointsOnLine(startPos
, endPos
, fillGaps
))
29 Vector3Int paintPos
= new Vector3Int(point
.x
, point
.y
, position
.z
);
30 base.Paint(grid
, brushTarget
, paintPos
);
33 lineStartActive
= false;
38 lineStartActive
= true;
42 [MenuItem("Assets/Create/Line Brush")]
43 public static void CreateBrush()
45 string path
= EditorUtility
.SaveFilePanelInProject("Save Line Brush", "New Line Brush", "asset", "Save Line Brush", "Assets");
50 AssetDatabase
.CreateAsset(ScriptableObject
.CreateInstance
<LineBrush
>(), path
);
54 /// Added option to fill gaps for continuous lines.
56 public static IEnumerable
<Vector2Int
> GetPointsOnLine(Vector2Int startPos
, Vector2Int endPos
, bool fillGaps
)
58 var points
= GetPointsOnLine(startPos
, endPos
);
61 var rise
= endPos
.y
- startPos
.y
;
62 var run
= endPos
.x
- startPos
.x
;
64 if (rise
!= 0 || run
!= 0)
66 var extraStart
= startPos
;
67 var extraEnd
= endPos
;
70 if (Mathf
.Abs(rise
) >= Mathf
.Abs(run
))
86 else // Mathf.Abs(rise) < Mathf.Abs(run)
103 var extraPoints
= GetPointsOnLine(extraStart
, extraEnd
);
104 extraPoints
= extraPoints
.Except(new[] { extraEnd }
);
105 points
= points
.Union(extraPoints
);
113 // http://ericw.ca/notes/bresenhams-line-algorithm-in-csharp.html
114 public static IEnumerable
<Vector2Int
> GetPointsOnLine(Vector2Int p1
, Vector2Int p2
)
121 bool steep
= Math
.Abs(y1
- y0
) > Math
.Abs(x1
- x0
);
125 t
= x0
; // swap x0 and y0
128 t
= x1
; // swap x1 and y1
135 t
= x0
; // swap x0 and x1
138 t
= y0
; // swap y0 and y1
143 int dy
= Math
.Abs(y1
- y0
);
145 int ystep
= (y0
< y1
) ? 1 : -1;
147 for (int x
= x0
; x
<= x1
; x
++)
149 yield return new Vector2Int((steep
? y
: x
), (steep
? x
: y
));
161 [CustomEditor(typeof(LineBrush
))]
162 public class LineBrushEditor
: GridBrushEditor
164 private LineBrush lineBrush { get { return target as LineBrush; }
}
165 private Tilemap lastTilemap
;
167 public override void OnPaintSceneGUI(GridLayout grid
, GameObject brushTarget
, BoundsInt position
, GridBrushBase
.Tool tool
, bool executing
)
169 base.OnPaintSceneGUI(grid
, brushTarget
, position
, tool
, executing
);
170 if (lineBrush
.lineStartActive
)
172 Tilemap tilemap
= brushTarget
.GetComponent
<Tilemap
>();
174 lastTilemap
= tilemap
;
176 // Draw preview tiles for tilemap
177 Vector2Int startPos
= new Vector2Int(lineBrush
.lineStart
.x
, lineBrush
.lineStart
.y
);
178 Vector2Int endPos
= new Vector2Int(position
.x
, position
.y
);
179 if (startPos
== endPos
)
180 PaintPreview(grid
, brushTarget
, position
.min
);
183 foreach (var point
in LineBrush
.GetPointsOnLine(startPos
, endPos
, lineBrush
.fillGaps
))
185 Vector3Int paintPos
= new Vector3Int(point
.x
, point
.y
, position
.z
);
186 PaintPreview(grid
, brushTarget
, paintPos
);
190 if (Event
.current
.type
== EventType
.Repaint
)
192 var min
= lineBrush
.lineStart
;
193 var max
= lineBrush
.lineStart
+ position
.size
;
195 // Draws a box on the picked starting position
197 GL
.MultMatrix(GUI
.matrix
);
199 Handles
.color
= Color
.blue
;
200 Handles
.DrawLine(new Vector3(min
.x
, min
.y
, min
.z
), new Vector3(max
.x
, min
.y
, min
.z
));
201 Handles
.DrawLine(new Vector3(max
.x
, min
.y
, min
.z
), new Vector3(max
.x
, max
.y
, min
.z
));
202 Handles
.DrawLine(new Vector3(max
.x
, max
.y
, min
.z
), new Vector3(min
.x
, max
.y
, min
.z
));
203 Handles
.DrawLine(new Vector3(min
.x
, max
.y
, min
.z
), new Vector3(min
.x
, min
.y
, min
.z
));
210 public override void ClearPreview()
213 if (lastTilemap
!= null)
215 lastTilemap
.ClearAllEditorPreviewTiles();